package close.kenny.lib.kwindows.window
{
	/**
	 * KWindow 1.0
	 * @author close
	 */
	import close.kenny.lib.kwindows.window.events.KWindowEvent;
	import close.kenny.lib.kwindows.window.skin.KWindowSkin;
	
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	
	import mx.core.IVisualElementContainer;
	import mx.managers.CursorManager;
	
	import spark.components.Button;
	import spark.components.Panel;
	
	[Event(name="close", type="com.kenny.lib.window.events.KWindowEvent")]
	[Event(name="maximize", type="com.kenny.lib.window.events.KWindowEvent")]
	[Event(name="minimize", type="com.kenny.lib.window.events.KWindowEvent")]
	[Event(name="restore", type="com.kenny.lib.window.events.KWindowEvent")]
	[Event(name="focusstart", type="com.kenny.lib.window.events.KWindowEvent")]
	[Event(name="focusend", type="com.kenny.lib.window.events.KWindowEvent")]
	public class KWindow extends Panel
	{
		[Embed(source="/close/kenny/lib/kwindows/window/assets/resizeCursorH.gif")]
		private static var DEFAULT_RESIZE_CURSOR_HORIZONTAL:Class;
		
		[Embed(source="/close/kenny/lib/kwindows/window/assets/resizeCursorTLBR.gif")]
		private static var DEFAULT_RESIZE_CURSOR_TL_BR:Class;
		
		[Embed(source="/close/kenny/lib/kwindows/window/assets/resizeCursorTRBL.gif")]
		private static var DEFAULT_RESIZE_CURSOR_TR_BL:Class;
		
		[Embed(source="/close/kenny/lib/kwindows/window/assets/resizeCursorV.gif")]
		private static var DEFAULT_RESIZE_CURSOR_VERTICAL:Class;
		
		public function KWindow()
		{
			super();
			setStyle("cornerRadius", 6);
			setStyle("skinClass",KWindowSkin);
			windowState=KWindowState.NORMAL;
		}
		
		//改变窗口尺寸的按钮=========start==============
		[SkinPart(required="false")]
		public var bottomLeftResizeButton:Button;
		
		[SkinPart(required="false")]
		public var bottomResizeButton:Button;
		
		[SkinPart(required="false")]
		public var bottomRightResizeButton:Button;
		
		[SkinPart(required="false")]
		public var leftResizeButton:Button;
		
		[SkinPart(required="false")]
		public var rightResizeButton:Button;
		
		[SkinPart(required="false")]
		public var topLeftResizeButton:Button;
		
		[SkinPart(required="false")]
		public var topResizeButton:Button;
		
		[SkinPart(required="false")]
		public var topRightResizeButton:Button;
		//改变窗口尺寸的按钮=========end==============
		
		//控制窗口状态的按钮=========start==============
		[SkinPart(required="false")]
		public var minimizeButton:Button;
		
		[SkinPart(required="false")]
		public var restoreButton:Button;
		
		[SkinPart(required="false")]
		public var maximizeButton:Button;
		
		[SkinPart(required="false")]
		public var closeButton:Button;
		//控制窗口状态的按钮=========end==============
		
		private var _hasFocus:Boolean;
		
		private var _windowState:int;
		
		private var currentResizeHandle:Button;
		
		private var dragAmountX:Number;
		
		private var dragAmountY:Number;
		
		private var dragMaxX:Number;
		
		private var dragMaxY:Number;
		
		private var dragStartMouseX:Number;
		
		private var dragStartMouseY:Number;
		
		private var normalHeight:Number;
		
		private var normalWidth:Number;
		
		private var normalX:Number;
		
		private var normalY:Number;
		
		private var savedWindowRect:Rectangle;
		
		private var _maximizable:Boolean=true;
		
		private var _minimizable:Boolean=true;
		
		private var _resizable:Boolean=true;
		
		private var _closable:Boolean=true;
		
		private var _dragable:Boolean=true;
		
		public function get dragable():Boolean
		{
			return _dragable;
		}
		
		public function set dragable(value:Boolean):void
		{
			_dragable = value;
		}
		
		public function get closable():Boolean
		{
			return _closable;
		}
		
		public function set closable(value:Boolean):void
		{
			_closable = value;
		}
		
		public function get resizable():Boolean
		{
			return _resizable;
		}
		
		public function set resizable(value:Boolean):void
		{
			_resizable = value;
		}
		
		public function get minimizable():Boolean
		{
			return _minimizable;
		}
		
		public function set minimizable(value:Boolean):void
		{
			_minimizable = value;
		}
		
		public function get maximizable():Boolean
		{
			return _maximizable;
		}
		
		public function set maximizable(value:Boolean):void
		{
			_maximizable = value;
		}
		
		public function get hasFocus():Boolean
		{
			return _hasFocus;
		}
		
		public function set hasFocus(value:Boolean):void
		{
			if (_hasFocus == value)
			{
				return;
			}
			
			_hasFocus=value;
			focusHandle();
		}
		
		private function focusHandle():void
		{
			if (hasFocus == true)
			{
				this.alpha=1;
				IVisualElementContainer(parent).setElementIndex(this, this.parent.numChildren - 1);
				dispatchEvent(new KWindowEvent(KWindowEvent.FOCUS_START));
			}
			else
			{
				this.alpha=0.6;
				dispatchEvent(new KWindowEvent(KWindowEvent.FOCUS_END));
			}
		}
		
		/**
		 * 按住窗口标题开始移动时调用
		 */
		private function dragStart(event:MouseEvent):void
		{
			if (windowState == KWindowState.NORMAL)
			{
				this.startDrag(false, new Rectangle(0, 0, parent.width - this.width, parent.height - this.height));
			}
			systemManager.addEventListener(MouseEvent.MOUSE_UP, dragStop);
			systemManager.stage.addEventListener(Event.MOUSE_LEAVE, dragStop);
		}
		
		/**
		 * 按住窗口标题停止移动时调用
		 */
		private function dragStop(event:Event):void
		{
			this.stopDrag();
			systemManager.removeEventListener(MouseEvent.MOUSE_UP, dragStop);
			systemManager.stage.removeEventListener(Event.MOUSE_LEAVE, dragStop);
		}
		
		/**
		 * 派发最小化事件
		 */
		private function minimize(event:MouseEvent):void
		{
			dispatchEvent(new KWindowEvent(KWindowEvent.MINIMIZE));
		}
		
		/**
		 * 窗口向下还原时调用
		 */
		private function restore():void
		{
			if (windowState == KWindowState.MAXIMIZED)
			{
				this.x=this.normalX;
				this.y=this.normalY;
				this.width=this.normalWidth;
				this.height=this.normalHeight;
				windowState=KWindowState.NORMAL;
				restoreButton.visible=false;
				restoreButton.enabled=false;
				maximizeButton.visible=true;
				maximizeButton.enabled=true;
				dispatchEvent(new KWindowEvent(KWindowEvent.RESTORE));
			}
		}
		
		/**
		 * 窗口最大化时调用
		 */
		private function maximize():void
		{
			if (windowState == KWindowState.NORMAL)
			{
				normalX=this.x;
				normalY=this.y;
				normalHeight=this.height;
				normalWidth=this.width;
				
				this.x=0;
				this.y=0;
				this.percentHeight=100;
				this.percentWidth=100;
				windowState=KWindowState.MAXIMIZED;
				maximizeButton.visible=false;
				maximizeButton.enabled=false;
				restoreButton.visible=true;
				restoreButton.enabled=true;
				dispatchEvent(new KWindowEvent(KWindowEvent.MAXIMIZE));
			}
		}
		
		/**
		 * 派发关闭事件
		 */
		private function close(event:MouseEvent):void
		{
			dispatchEvent(new KWindowEvent(KWindowEvent.CLOSE));
		}
		
		/**
		 * 在窗口标题双击时调用
		 */
		private function titleDoubleClick(event:MouseEvent):void
		{
			if (windowState == KWindowState.NORMAL)
			{
				maximize();
			}
			else
			{
				restore();
			}
		}
		
		/**
		 * 窗口尺寸改变时调用
		 */
		private function resize(event:Event):void
		{
			dragAmountX=parent.mouseX - dragStartMouseX;
			dragAmountY=parent.mouseY - dragStartMouseY;
			if (currentResizeHandle == topResizeButton && parent.mouseY > 0)
			{
				this.y=Math.min(savedWindowRect.y + dragAmountY, dragMaxY);
				this.height=Math.max(savedWindowRect.height - dragAmountY, this.skin.minHeight);
				
			}
			else if (currentResizeHandle == rightResizeButton)
			{
				this.width=Math.max(savedWindowRect.width + dragAmountX, this.skin.minWidth);
			}
			else if (currentResizeHandle == bottomResizeButton && parent.mouseY < parent.height)
			{
				this.height=Math.max(savedWindowRect.height + dragAmountY, this.skin.minHeight);
			}
			else if (currentResizeHandle == leftResizeButton && parent.mouseX > 0)
			{
				this.x=Math.min(savedWindowRect.x + dragAmountX, dragMaxX);
				this.width=Math.max(savedWindowRect.width - dragAmountX, this.skin.minWidth);
			}
			else if (currentResizeHandle == topLeftResizeButton && parent.mouseX > 0 && parent.mouseY > 0)
			{
				this.x=Math.min(savedWindowRect.x + dragAmountX, dragMaxX);
				this.y=Math.min(savedWindowRect.y + dragAmountY, dragMaxY);
				this.width=Math.max(savedWindowRect.width - dragAmountX, this.skin.minWidth);
				this.height=Math.max(savedWindowRect.height - dragAmountY, this.skin.minHeight);
			}
			else if (currentResizeHandle == topRightResizeButton && parent.mouseX < parent.width && parent.mouseY > 0)
			{
				this.y=Math.min(savedWindowRect.y + dragAmountY, dragMaxY);
				this.width=Math.max(savedWindowRect.width + dragAmountX, this.skin.minWidth);
				this.height=Math.max(savedWindowRect.height - dragAmountY, this.skin.minHeight);
			}
			else if (currentResizeHandle == bottomRightResizeButton && parent.mouseX < parent.width && parent.mouseY < parent.height)
			{
				this.width=Math.max(savedWindowRect.width + dragAmountX, this.skin.minWidth);
				this.height=Math.max(savedWindowRect.height + dragAmountY, this.skin.minHeight);
			}
			else if (currentResizeHandle == bottomLeftResizeButton && parent.mouseX > 0 && parent.mouseY < parent.height)
			{
				this.x=Math.min(savedWindowRect.x + dragAmountX, dragMaxX);
				this.width=Math.max(savedWindowRect.width - dragAmountX, this.skin.minWidth);
				this.height=Math.max(savedWindowRect.height + dragAmountY, this.skin.minHeight);
			}
		}
		
		/**
		 * 在窗口边缘并按下鼠标左键时调用
		 */
		private function resizeButtonDown(event:MouseEvent):void
		{
			if (windowState == KWindowState.NORMAL)
			{
				currentResizeHandle=event.target as Button;
				setCursor(currentResizeHandle);
				dragStartMouseX=parent.mouseX;
				dragStartMouseY=parent.mouseY;
				savedWindowRect=new Rectangle(this.x, this.y, this.width, this.height);
				dragMaxX=savedWindowRect.x + (savedWindowRect.width - this.skin.minWidth);
				dragMaxY=savedWindowRect.y + (savedWindowRect.height - this.skin.minHeight);
				systemManager.addEventListener(Event.ENTER_FRAME, resize);
				systemManager.addEventListener(MouseEvent.MOUSE_UP, resizeButtonRelease);
				systemManager.stage.addEventListener(Event.MOUSE_LEAVE, resizeButtonRelease);
			}
		}
		
		/**
		 * 在窗口边缘并弹开鼠标左键时调用
		 */
		private function resizeButtonRelease(event:MouseEvent):void
		{
			currentResizeHandle=null;
			systemManager.removeEventListener(Event.ENTER_FRAME, resize);
			systemManager.removeEventListener(MouseEvent.MOUSE_UP, resizeButtonRelease);
			systemManager.stage.removeEventListener(Event.MOUSE_LEAVE, resizeButtonRelease);
			CursorManager.removeAllCursors();
		}
		
		/**
		 * 在窗口边缘并鼠标离开时调用
		 */
		private function resizeButtonRollOut(event:MouseEvent):void
		{
			if (!event.buttonDown)
				CursorManager.removeAllCursors();
		}
		
		/**
		 * 在窗口边缘并鼠标进入时调用
		 */
		private function resizeButtonRollOver(event:MouseEvent):void
		{
			if (windowState == KWindowState.NORMAL)
			{
				if (!event.buttonDown)
				{
					setCursor(event.target as Button);
				}
			}
		}
		
		/**
		 * 鼠标经过窗口边缘时设置鼠标显示形状
		 */
		private function setCursor(target:Button):void
		{
			switch (target)
			{
				case topResizeButton:
				case bottomResizeButton:
					CursorManager.setCursor(DEFAULT_RESIZE_CURSOR_VERTICAL, 2, -10, -10);
					break;
				case rightResizeButton:
				case leftResizeButton:
					CursorManager.setCursor(DEFAULT_RESIZE_CURSOR_HORIZONTAL, 2, -10, -10);
					break;
				case topLeftResizeButton:
				case bottomRightResizeButton:
					CursorManager.setCursor(DEFAULT_RESIZE_CURSOR_TL_BR, 2, -10, -10);
					break;
				case topRightResizeButton:
				case bottomLeftResizeButton:
					CursorManager.setCursor(DEFAULT_RESIZE_CURSOR_TR_BL, 2, -10, -10);
					break;
			}
		}
		
		/**
		 * 窗口初始化时调用该函数加载皮肤
		 */
		override protected function partAdded(partName:String, instance:Object):void
		{
			super.partAdded(partName, instance);
			if (instance == titleDisplay)
			{
				if(dragable)
				{
					titleDisplay.addEventListener(MouseEvent.MOUSE_DOWN, dragStart);
					titleDisplay.addEventListener(MouseEvent.MOUSE_UP, dragStop);
				}
				if(maximizable)
				{
					titleDisplay.addEventListener(MouseEvent.DOUBLE_CLICK, titleDoubleClick);
				}
			}
			
			if (instance == closeButton)
			{
				if(closable)
				{
					closeButton.addEventListener(MouseEvent.CLICK, close);
				}
				else
				{
					closeButton.visible=false;
					closeButton.enabled=false;
				}
			}
			if (instance == maximizeButton)
			{
				if(maximizable)
				{
					maximizeButton.addEventListener(MouseEvent.CLICK, titleDoubleClick);
				}
				else
				{
					maximizeButton.visible=false;
					maximizeButton.enabled=false;
				}
			}
			if (instance == restoreButton)
			{
				restoreButton.visible=false;
				restoreButton.enabled=false;
				if(maximizable)
				{
					restoreButton.addEventListener(MouseEvent.CLICK, titleDoubleClick);	
				}
			}
			if (instance == minimizeButton)
			{
				if(minimizable)
				{
					minimizeButton.addEventListener(MouseEvent.CLICK, minimize);
				}
				else
				{
					minimizeButton.visible=false;
					minimizeButton.enabled=false;
				}
			}
			if (instance == topResizeButton)
			{
				if(resizable)
				{
					topResizeButton.addEventListener(MouseEvent.ROLL_OVER, resizeButtonRollOver);
					topResizeButton.addEventListener(MouseEvent.MOUSE_DOWN, resizeButtonDown);
					topResizeButton.addEventListener(MouseEvent.ROLL_OUT, resizeButtonRollOut);
				}
				else
				{
					topResizeButton.visible=false;
					topResizeButton.enabled=false;
					
				}
			}
			if (instance == bottomResizeButton)
			{
				if(resizable)
				{
					bottomResizeButton.addEventListener(MouseEvent.ROLL_OVER, resizeButtonRollOver)
					bottomResizeButton.addEventListener(MouseEvent.MOUSE_DOWN, resizeButtonDown)
					bottomResizeButton.addEventListener(MouseEvent.ROLL_OUT, resizeButtonRollOut)
				}
				else
				{
					bottomResizeButton.visible=false;
					bottomResizeButton.enabled=false;
				}
			}
			if (instance == leftResizeButton)
			{
				if(resizable)
				{
					leftResizeButton.addEventListener(MouseEvent.ROLL_OVER, resizeButtonRollOver);
					leftResizeButton.addEventListener(MouseEvent.MOUSE_DOWN, resizeButtonDown);
					leftResizeButton.addEventListener(MouseEvent.ROLL_OUT, resizeButtonRollOut);
				}
				else
				{
					leftResizeButton.visible=false;
					leftResizeButton.enabled=false;
				}
			}
			if (instance == rightResizeButton)
			{
				if(resizable)
				{
					rightResizeButton.addEventListener(MouseEvent.ROLL_OVER, resizeButtonRollOver)
					rightResizeButton.addEventListener(MouseEvent.MOUSE_DOWN, resizeButtonDown)
					rightResizeButton.addEventListener(MouseEvent.ROLL_OUT, resizeButtonRollOut)
				}
				else
				{
					rightResizeButton.visible=false;
					rightResizeButton.enabled=false;
				}
			}
			if (instance == topLeftResizeButton)
			{
				if(resizable)
				{
					topLeftResizeButton.addEventListener(MouseEvent.ROLL_OVER, resizeButtonRollOver)
					topLeftResizeButton.addEventListener(MouseEvent.MOUSE_DOWN, resizeButtonDown)
					topLeftResizeButton.addEventListener(MouseEvent.ROLL_OUT, resizeButtonRollOut)
				}
				else
				{
					topLeftResizeButton.visible=false;
					topLeftResizeButton.enabled=false;
				}
			}
			if (instance == topRightResizeButton)
			{
				if(resizable)
				{
					topRightResizeButton.addEventListener(MouseEvent.ROLL_OVER, resizeButtonRollOver);
					topRightResizeButton.addEventListener(MouseEvent.MOUSE_DOWN, resizeButtonDown);
					topRightResizeButton.addEventListener(MouseEvent.ROLL_OUT, resizeButtonRollOut);
				}
				else
				{
					topRightResizeButton.visible=false;
					topRightResizeButton.enabled=false;
				}
			}
			if (instance == bottomLeftResizeButton)
			{
				if(resizable)
				{
					bottomLeftResizeButton.addEventListener(MouseEvent.ROLL_OVER, resizeButtonRollOver);
					bottomLeftResizeButton.addEventListener(MouseEvent.MOUSE_DOWN, resizeButtonDown);
					bottomLeftResizeButton.addEventListener(MouseEvent.ROLL_OUT, resizeButtonRollOut);
				}
				else
				{
					bottomLeftResizeButton.visible=false;
					bottomLeftResizeButton.enabled=false;
				}
			}
			if (instance == bottomRightResizeButton)
			{
				if(resizable)
				{
					bottomRightResizeButton.addEventListener(MouseEvent.ROLL_OVER, resizeButtonRollOver);
					bottomRightResizeButton.addEventListener(MouseEvent.MOUSE_DOWN, resizeButtonDown);
					bottomRightResizeButton.addEventListener(MouseEvent.ROLL_OUT, resizeButtonRollOut);
				}
				else
				{
					bottomRightResizeButton.visible=false;
					bottomRightResizeButton.enabled=false;
				}
			}
		}
		
		/**
		 * 窗口销毁时调用该函数卸载皮肤
		 */
		override protected function partRemoved(partName:String, instance:Object):void
		{
			super.partRemoved(partName, instance);
			if (instance == titleDisplay)
			{
				titleDisplay.removeEventListener(MouseEvent.MOUSE_DOWN, dragStart);
				titleDisplay.removeEventListener(MouseEvent.MOUSE_UP, dragStop);
				titleDisplay.removeEventListener(MouseEvent.DOUBLE_CLICK, titleDoubleClick)
			}
			if (instance == closeButton)
			{
				closeButton.removeEventListener(MouseEvent.CLICK, close);
			}
			if (instance == restoreButton)
			{
				restoreButton.removeEventListener(MouseEvent.CLICK, maximize);
			}
			if (instance == maximizeButton)
			{
				maximizeButton.removeEventListener(MouseEvent.CLICK, titleDoubleClick);
			}
			if (instance == minimizeButton)
			{
				minimizeButton.removeEventListener(MouseEvent.CLICK, minimize);
			}
			if (instance == topResizeButton)
			{
				topResizeButton.removeEventListener(MouseEvent.ROLL_OVER, resizeButtonRollOver)
				topResizeButton.removeEventListener(MouseEvent.MOUSE_DOWN, resizeButtonDown)
				topResizeButton.removeEventListener(MouseEvent.ROLL_OUT, resizeButtonRollOut)
			}
			if (instance == bottomResizeButton)
			{
				bottomResizeButton.removeEventListener(MouseEvent.ROLL_OVER, resizeButtonRollOver)
				bottomResizeButton.removeEventListener(MouseEvent.MOUSE_DOWN, resizeButtonDown)
				bottomResizeButton.removeEventListener(MouseEvent.ROLL_OUT, resizeButtonRollOut)
			}
			if (instance == leftResizeButton)
			{
				leftResizeButton.removeEventListener(MouseEvent.ROLL_OVER, resizeButtonRollOver)
				leftResizeButton.removeEventListener(MouseEvent.MOUSE_DOWN, resizeButtonDown)
				leftResizeButton.removeEventListener(MouseEvent.ROLL_OUT, resizeButtonRollOut)
			}
			if (instance == rightResizeButton)
			{
				rightResizeButton.removeEventListener(MouseEvent.ROLL_OVER, resizeButtonRollOver)
				rightResizeButton.removeEventListener(MouseEvent.MOUSE_DOWN, resizeButtonDown)
				rightResizeButton.removeEventListener(MouseEvent.ROLL_OUT, resizeButtonRollOut)
			}
			if (instance == topLeftResizeButton)
			{
				topLeftResizeButton.removeEventListener(MouseEvent.ROLL_OVER, resizeButtonRollOver)
				topLeftResizeButton.removeEventListener(MouseEvent.MOUSE_DOWN, resizeButtonDown)
				topLeftResizeButton.removeEventListener(MouseEvent.ROLL_OUT, resizeButtonRollOut)
			}
			if (instance == topRightResizeButton)
			{
				topRightResizeButton.removeEventListener(MouseEvent.ROLL_OVER, resizeButtonRollOver)
				topRightResizeButton.removeEventListener(MouseEvent.MOUSE_DOWN, resizeButtonDown)
				topRightResizeButton.removeEventListener(MouseEvent.ROLL_OUT, resizeButtonRollOut)
			}
			if (instance == bottomLeftResizeButton)
			{
				bottomLeftResizeButton.removeEventListener(MouseEvent.ROLL_OVER, resizeButtonRollOver)
				bottomLeftResizeButton.removeEventListener(MouseEvent.MOUSE_DOWN, resizeButtonDown)
				bottomLeftResizeButton.removeEventListener(MouseEvent.ROLL_OUT, resizeButtonRollOut)
			}
			if (instance == bottomRightResizeButton)
			{
				bottomRightResizeButton.removeEventListener(MouseEvent.ROLL_OVER, resizeButtonRollOver)
				bottomRightResizeButton.removeEventListener(MouseEvent.MOUSE_DOWN, resizeButtonDown)
				bottomRightResizeButton.removeEventListener(MouseEvent.ROLL_OUT, resizeButtonRollOut)
			}
		}
		
		private function get windowState():int
		{
			return _windowState;
		}
		
		private function set windowState(windowState:int):void
		{
			_windowState=windowState;
		}
		/**
		 * 以 Point 对象的形式返回窗口原点的坐标。Point 对象的 x 字段包含此窗口原点的 x 坐标，而 Point 对象的 y 字段则包含此窗口原点的 y 坐标。
		 * @return 
		 */
		public function getPosition():Point
		{
			return new Point(this.x, this.y);
		}
		
		/**
		 * 调整窗口原点的坐标，使其当前x坐标为 p.x，当前y坐标为 p.y。 
		 * @param p
		 */
		public function setPosition(p:Point):void
		{
			this.x = p.x;
			this.y = p.y;
		}
	}
}